/*
 * Copyright (c) 2021. Dylan Cai
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

@file:Suppress("unused")

package com.price.common.extend

import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch

/**
 *解决写重复代码
 *并且最早在 View处于 STARTED状态时从数据流收集数据，并在
 *生命周期进入 STOPPED状态时 STOPPED（停止）收集操作。
 *它会在生命周期再次进入 STARTED状态时自动开始进行数据收集操作。
 */
//扩展函数,加上repeatOnlifecycle
//这个在于协程会被自动挂起,在处理事务时无法被直接取消,所以建议用这个挂起
inline fun <T> Flow<T>.launchAndCollectIn(
    owner: LifecycleOwner,
    minActiveState: Lifecycle.State = Lifecycle.State.STARTED,
    crossinline action: suspend CoroutineScope.(T) -> Unit
) {
    owner.lifecycleScope.launch {
        owner.lifecycle.repeatOnLifecycle(minActiveState) {
            collect {
                action(it)
            }
        }
    }
}
//-----------------Flow扩展内联函数--------------------------------//
fun NormalCoroutineScope(): CoroutineScope {
    val job = Job()
    val coroutineScope = CoroutineScope(job)
    return coroutineScope;
}

/**
 * data->初始数据
 * dispatcher - >调度器
 * action -->需要初始赋值的函数
 */
inline fun <reified T> createFlow(
    data: T,
    dispatcher: CoroutineDispatcher = Dispatchers.Default,
    viewModelScope: CoroutineScope = NormalCoroutineScope(),
    //   在内联函数中必须添加 noinline ->用作于不被内联函数影响,生成一个匿名内部类
    //or crossinline 保证了函数只能return当前这个lambda

    //你看到的CoroutineScope.()其实是具体的具象, 它可以是任何对象。比如 View.(Int)->Unit
    //这里需要思考一下,为什么这么做.添加了CoroutineScope,因为它是协程,所以添加这个协程的作用域
    //该高阶函数需要一个参数,然后可以传到外面去
    crossinline action: suspend CoroutineScope.(MutableStateFlow<T>) -> Unit = {}
): MutableStateFlow<T> {
    return MutableStateFlow(data).also {
        viewModelScope.launch(dispatcher) {
            //回调返回使其可以做任意操作
            action(it)
        }
    }
}